#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    File Name:      adb_utils
    Author:         'daze'
    date:           2018/12/7
"""
import os

from AutoWool.main.config.config_utils import ConfigUtils
from AutoWool.main.config.constants import Constants
from AutoWool.main.utils.log_utils import Log
from AutoWool.main.utils.opencv_utils import OpencvUtils
from AutoWool.main.utils.system_utils import SystemUtils


class AdbUtils:
    emu_screen_w = 0
    emu_screen_h = 0
    phone_screen_shot_img_name = 'phone_screen_shot.png'

    # 获取手机屏幕的宽高大小
    @staticmethod
    def get_phy_size():
        return SystemUtils.execute_os_popen_cmd('adb shell wm size')

    # 获取手机屏幕宽
    @staticmethod
    def get_phy_w():
        if AdbUtils.emu_screen_w == 0:
            phy_size_str = AdbUtils.get_phy_size()
            if phy_size_str is None or phy_size_str == '':
                Log.error('无法获取到手机屏幕宽,请检查手机设备是否连接')
            AdbUtils.emu_screen_w = int(phy_size_str.split(' ')[2].split('x')[0])
        return AdbUtils.emu_screen_w

    # 获取手机屏幕高
    @staticmethod
    def get_phy_h():
        if AdbUtils.emu_screen_h == 0:
            phy_size_str = AdbUtils.get_phy_size()
            if phy_size_str is None or phy_size_str == '':
                Log.error('无法获取到手机屏幕高,请检查手机设备是否连接')
            AdbUtils.emu_screen_h = int(phy_size_str.split(' ')[2].split('x')[1])
        return AdbUtils.emu_screen_h

    # 唤醒屏幕，默认是点击电源键才唤醒，即使设置为双击屏幕可以唤醒模拟双击也白扯，只能设置为永不休眠
    @staticmethod
    def awake_screen():
        SystemUtils.execute_os_sys_cmd('adb shell input tap 200 200')
        SystemUtils.execute_os_sys_cmd('adb shell input tap 200 200')
        print('如果无效请设置永不休眠')

    # 判断是否锁屏 poweroff,返回 false 即为 lock，这个在红米手机上不准，除非锁屏并黑屏才为 true，但是解锁没有用
    @staticmethod
    def judge_is_lock_screen() -> bool:
        result: str = SystemUtils.execute_os_popen_cmd('adb shell dumpsys window policy|grep mScreenOnFully')
        return result.split(' ')[1].split('=')[1] == 'false'

    @staticmethod
    def input_content(content: str):
        SystemUtils.execute_os_sys_cmd('adb shell input text ' + content)

    # 收起软键盘
    @staticmethod
    def retract_keyboard():
        SystemUtils.execute_os_sys_cmd('adb shell input keyevent 111')

    # 解锁屏幕，这个红米手机上锁屏并黑屏解锁没有用
    @staticmethod
    def unlock_phone_screen():
        # 亮屏
        AdbUtils.input_key_event(Constants.AdbKeyCode.KEY_POWER)
        # 解锁
        AdbUtils.swipe(500, 700, 500, 50)

    # 获得当前 activity 的包名和activity名
    @staticmethod
    def get_cur_package_activity_name():
        return SystemUtils.execute_os_popen_cmd('adb shell dumpsys window | findstr mCurrentFocus')

    # 安装应用
    @staticmethod
    def install_app(apk_abs_path):
        SystemUtils.execute_os_sys_cmd('adb install ' + apk_abs_path)
        print('安装 ' + apk_abs_path + ' 完毕')

    # 卸载应用
    @staticmethod
    def uninstall_app(package_name):
        SystemUtils.execute_os_sys_cmd('adb uninstall ' + package_name)
        print('卸载 ' + package_name + ' 完毕')

    # 打开指定应用
    @staticmethod
    def open_target_app(app_package_activity_name: str):
        result = SystemUtils.execute_os_popen_cmd('adb shell am start -n  ' + app_package_activity_name)
        print('result=' + result)

    # 杀死当前 app 进程
    @staticmethod
    def kill_cur_app_process(app_package_name: str):
        print('开始杀死 app 进程,包名为:' + app_package_name)
        SystemUtils.execute_os_sys_cmd('adb shell am force-stop ' + app_package_name)

    # 模拟手机点击，注意：一定要开启 usb 安全权限(可以模拟点击)，否则命令无效
    @staticmethod
    def click(*point):
        SystemUtils.delayTime(1)  # 延迟一秒
        SystemUtils.execute_os_sys_cmd('adb shell input tap ' + str(point[0]) + ' ' + str(point[1]))
        SystemUtils.delayTime(1)  # 延迟一秒

    # 模拟手机滑动
    @staticmethod
    def swipe(start_x, start_y, end_x, end_y):
        SystemUtils.execute_os_sys_cmd(
            'adb shell input swipe ' + str(start_x) + ' ' + str(start_y) + ' ' + str(end_x) + ' ' + str(end_y))

    # 手指由上到下滑动
    @staticmethod
    def scroll_top_to_bottom():
        AdbUtils.swipe(0, 0, 3000, 3000)

    # 手指由下到上滑动
    @staticmethod
    def scroll_bottom_to_top():
        AdbUtils.swipe(500, 1000, 500, 0)  # x 取 500 做为中间位置

    # 注意：一定要开启 设置 -> 开发者选项 里一定要开启 usb 安装和 usb 调试(安全设置)
    @staticmethod
    def input_key_event(keyevent_code: int):
        SystemUtils.execute_os_sys_cmd('adb shell input keyevent ' + str(keyevent_code))

    # 删除键，注意 一定要开启：设置 -> 开发者选项 里一定要开启 usb 安装和 usb 调试(安全设置)
    @staticmethod
    def delete_content():
        AdbUtils.input_key_event(Constants.AdbKeyCode.KEY_BACKSPACE)

    # 清空输入框(当前输入框必须已经有焦点了)
    @staticmethod
    def clear_input_area():
        for i in range(20):  # 一直删除20个字符
            AdbUtils.delete_content()

    # 将本地文件 push 到手机
    @staticmethod
    def push_file_to_phone(local_file_abs_path, phone_dir):
        SystemUtils.execute_os_sys_cmd('adb push ' + local_file_abs_path + ' ' + phone_dir)

    # 从手机 pull 文件到本地
    @staticmethod
    def pull_file_from_phone(local_dir, phone_file_abs_path):
        SystemUtils.execute_os_sys_cmd('adb pull ' + phone_file_abs_path + ' ' + local_dir)

    # 判断手机目录中文件是否存在
    @staticmethod
    def is_file_exist(file_dir, target_file_name):
        Log.log('adb_utils 开始判断 ' + file_dir + ' 中的 ' + target_file_name + ' 是否存在')
        result = SystemUtils.execute_os_popen_cmd('adb shell ls ' + file_dir).split('\n')  # storage/emulated/legacy/
        file_exist = False
        for ele in result:
            if ele is not None and ele != '' and ele != '\n':
                if str(ele).index(target_file_name) != -1:
                    file_exist = True
                    Log.log('adb_utils ' + file_dir + ' 中的 ' + target_file_name + ' 存在')
        return file_exist

    # 删除指定目录中的所有文件
    @staticmethod
    def delete_dir_content(path_dir):
        Log.log('adb_utils 开始删除 ' + path_dir + ' 中的所有文件')
        result = SystemUtils.execute_os_popen_cmd('adb shell ls ' + path_dir).split('\n')  # storage/emulated/legacy/
        if len(result) != 0:
            Log.log(path_dir + ' 中有 ' + str(len(result)) + ' 个文件，开始删除')
            for ele in result:
                if ele is not None and ele != '' and ele != '\n':
                    delete_abs_path = path_dir + '/' + ele
                    Log.log('开始使用 adb 删除 ' + delete_abs_path)
                    SystemUtils.execute_os_sys_cmd('adb shell rm ' + delete_abs_path)
        else:
            Log.log(path_dir + ' 中没有文件，不删除')
        Log.log('adb_utils delete_dir_content 执行完毕')

    # 获取(l,t,r,b)的中心点
    @staticmethod
    def get_tuple_center_point(loc_w_h_tuple) -> ():
        if len(loc_w_h_tuple) != 4:
            Log.error('get_tuple_center_point loc_w_h_tuple!= 4')
        center_x = loc_w_h_tuple[0] + loc_w_h_tuple[2] / 2
        center_y = loc_w_h_tuple[1] + loc_w_h_tuple[3] / 2
        return center_x, center_y

    # 截取手机屏幕并 pull 到本地
    @staticmethod
    def screen_cap_and_pull(clip_img_name=None):
        if clip_img_name is None:
            clip_img_name = AdbUtils.phone_screen_shot_img_name
        template_img_abs_path = os.path.join(ConfigUtils.Dir.get_img_dir_abs_path(), clip_img_name)
        SystemUtils.execute_os_sys_cmd('adb shell screencap -p /sdcard/' + clip_img_name)
        SystemUtils.execute_os_sys_cmd('adb pull /sdcard/' + clip_img_name + ' ' + template_img_abs_path)

    # 判断手机截图中该图片是否存在
    # 注意：使用该方法如果换了手机则之前的图片可能找不到，从而报错，而且比模拟点击效率低，所以只在判断是否登录时使用
    @staticmethod
    def is_phone_img_exist(img_name) -> ():
        template_img_abs_path = os.path.join(ConfigUtils.Dir.get_img_dir_abs_path(), img_name)
        Log.log('cur_png_abs_path=' + template_img_abs_path)
        if not os.path.exists(template_img_abs_path):
            Log.error(str(img_name) + '图片不存在')
        # 截手机屏到本地
        AdbUtils.screen_cap_and_pull()
        src_img_abs_path = os.path.join(ConfigUtils.Dir.get_img_dir_abs_path(), AdbUtils.phone_screen_shot_img_name)
        if not os.path.exists(src_img_abs_path):
            Log.error(str(src_img_abs_path) + ' 图片不存在')
        # 通过 Opencv 获取模板图片的 location
        result_loc_w_h_tuple = OpencvUtils.get_template_img_loc_w_h(src_img_abs_path, template_img_abs_path)
        # 删除 _img 下的该图片
        # FileUtils.delete_file(src_img_abs_path)
        return result_loc_w_h_tuple

    # 注意：使用该方法如果换了手机则之前的图片可能找不到，从而报错，而且比模拟点击效率低，所以只在判断是否登录时使用
    @staticmethod
    def click_img_center(img_name) -> ():
        result_loc_w_h_tuple = AdbUtils.is_phone_img_exist(img_name)
        if result_loc_w_h_tuple != ():
            Log.log('在手机截屏中找到了 ' + img_name + ' result_loc_w_h_tuple=' + str(result_loc_w_h_tuple))
            center_point_tuple = AdbUtils.get_tuple_center_point(result_loc_w_h_tuple)
            Log.log('开始点击手机中心点: ' + str(center_point_tuple))
            AdbUtils.click(*center_point_tuple)
            return result_loc_w_h_tuple
        else:
            Log.debug('没有在手机中找到 ' + img_name)
            return ()
